home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
nn.zip
/
DB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-29
|
11KB
|
548 lines
/*
* database access and update
*/
#include "config.h"
#include "db.h"
export master_header master;
export group_header *active_groups, **sorted_groups;
/*
* Init access to a group
*/
export group_header *current_group = NULL;
export char group_path_name[FILENAME];
export char *group_file_name = NULL;
static char *group_position = NULL;
init_group(gh)
register group_header *gh;
{
register char *p, *q;
if (gh == NULL) return 0;
if (gh == current_group) return 1;
current_group = gh;
if (gh->group_flag & G_FOLDER) {
group_position = NULL;
group_file_name = NULL;
strcpy(group_path_name, gh->group_name);
return 1;
}
#ifdef NNTP
if (use_nntp && nntp_set_group(gh) < 0)
return 0;
#endif /* NNTP */
if (group_position == NULL)
if (is_master)
group_position = group_path_name;
else {
strcpy(group_path_name, news_directory);
group_position = group_path_name + strlen(group_path_name);
*group_position++ = '/';
}
for (p = group_position, q = gh->group_name; *q; q++)
*p++ = (*q == '.') ? '/' : *q;
if (is_master) {
/*
* The master will chdir to the group's directory to
* get better performance (can use relative path names).
*
* We cannot do the same for the user client, because of
* the 'save' commands.
*/
*p++ = NUL;
#ifdef NNTP
if (!use_nntp) {
#endif
if (chdir(news_directory) < 0)
sys_error(news_directory);
if (chdir(group_path_name) < 0)
return 0;
#ifdef NNTP
}
#endif /* NNTP */
group_file_name = group_path_name;
} else {
/* client */
if (gh->group_flag & G_NO_DIRECTORY) return 0;
*p++ = '/';
group_file_name = p;
}
return 1;
}
FILE *open_groups(mode)
{
return open_file(relative(db_directory, "GROUPS"), mode);
}
/*
* Open master file; read it in if first open.
*/
FILE *master_file = NULL;
open_master(mode)
{
FILE *g;
int n, cur_group;
unsigned entries;
char *strings;
register group_header *gh;
static int first_open = 1;
master_file = open_file(relative(db_directory, "MASTER"), mode|MUST_EXIST);
if (mode == OPEN_CREATE || !first_open) return;
first_open = 0;
if (!db_read_master(master_file, &master))
sys_error("Incomplete MASTER");
master.free_groups = master.number_of_groups / 10;
entries = master.free_groups + master.number_of_groups;
active_groups = (group_header *) calloc(entries, sizeof(group_header));
mem_check(active_groups, entries, "group headers");
sorted_groups = (group_header **)
calloc(entries, sizeof(group_header *));
mem_check((char *)sorted_groups, entries, "sorted group header pointers");
strings = malloc((unsigned)master.next_group_write_offset);
mem_check(strings, (int)master.next_group_write_offset,
"bytes for group names");
g = open_groups(OPEN_READ|MUST_EXIST);
n = fread(strings, sizeof(char), (int)master.next_group_write_offset, g);
if (n != (int)master.next_group_write_offset)
sys_error("Incomplete GROUPS file");
fclose(g);
for (cur_group = 0, gh = active_groups;
cur_group < master.number_of_groups;
cur_group++, gh++) {
sorted_groups[cur_group] = gh;
if (!db_read_group(master_file, gh, -1))
sys_error("Incomplete MASTER file");
gh->group_num = cur_group;
gh->group_name = strings;
strings += gh->group_name_length;
*strings++ = NUL;
}
sort_groups();
}
close_master()
{
if (master_file != NULL) {
fclose(master_file);
master_file = NULL;
}
}
update_group(gh)
group_header *gh;
{
int32 flag;
flag = gh->group_flag & ~G_MASTER_FLAGS;
if (!db_read_group(master_file, gh, gh->group_num)) return -1;
gh->group_flag |= flag;
if (gh->group_flag & G_BLOCKED) return -1;
return 1;
}
static group_name_cmp(g1, g2)
group_header **g1, **g2;
{
return strcmp((*g1)->group_name, (*g2)->group_name);
}
sort_groups()
{
qsort((char *)sorted_groups, (unsigned)master.number_of_groups,
sizeof(group_header *), group_name_cmp);
}
group_header *lookup(name)
char *name;
{
register i, j, k, t;
i = 0; j = master.number_of_groups - 1;
while (i <= j) {
k = (i + j) / 2;
if ( (t=strcmp(name, sorted_groups[k]->group_name)) > 0)
i = k+1;
else
if (t < 0)
j = k-1;
else
return sorted_groups[k];
}
return NULL;
}
art_collected(gh, art_num)
group_header *gh;
article_number art_num;
{
return gh->first_l_article <= art_num && gh->last_l_article >= art_num;
}
FILE *open_data_file(gh, d_or_x, mode)
group_header *gh;
char d_or_x;
int mode;
{
char data_file[FILENAME];
sprintf(data_file, "%s/DATA/%d.%c", db_directory, gh->group_num, d_or_x);
if (mode == -1) {
unlink(data_file);
return (FILE *)NULL;
} else
return open_file(data_file, mode);
}
#ifdef NETWORK_DATABASE
#define MASTER_FIELDS 3
#define GROUP_FIELDS 6
#define ARTICLE_FIELDS 10
typedef int32 net_long;
#ifdef NETWORK_BYTE_ORDER
#define net_to_host(buf, n)
#define host_to_net(buf, n)
#else
static net_to_host(buf, lgt)
register net_long *buf;
int lgt;
{
while (--lgt >= 0) {
*buf = ntohl(*buf);
buf++;
}
}
static host_to_net(buf, lgt)
register net_long *buf;
int lgt;
{
while (--lgt >= 0) {
*buf = htonl(*buf);
buf++;
}
}
#endif /* not NETWORK_BYTE_ORDER */
#endif /* NETWORK_DATABASE */
db_read_master(f, masterp)
FILE *f;
master_header *masterp;
{
#ifdef NETWORK_DATABASE
net_long buf[MASTER_FIELDS];
if (fread(buf, sizeof(net_long), MASTER_FIELDS, f) != MASTER_FIELDS)
return 0;
net_to_host(buf, MASTER_FIELDS);
masterp->last_scan = buf[0];
masterp->number_of_groups = buf[1];
masterp->next_group_write_offset = buf[2];
#else
if (fread(masterp, sizeof(master_header), 1, f) != 1) return 0;
#endif
return 1;
}
db_write_master(f, masterp)
FILE *f;
master_header *masterp;
{
#ifdef NETWORK_DATABASE
net_long buf[MASTER_FIELDS];
buf[0] = masterp->last_scan;
buf[1] = masterp->number_of_groups;
buf[2] = masterp->next_group_write_offset;
host_to_net(buf, MASTER_FIELDS);
if (fwrite(buf, sizeof(net_long), MASTER_FIELDS, f) != MASTER_FIELDS) return 0;
#else
if (fwrite((char *)masterp, sizeof(master_header), 1, f) != 1) return 0;
#endif
return 1;
}
db_read_group(f, gh, n)
FILE *f;
register group_header *gh;
group_number n;
{
#ifdef NETWORK_DATABASE
net_long buf[GROUP_FIELDS];
if (n >= 0)
fseek(f, MASTER_FIELDS * sizeof(net_long) + GROUP_FIELDS * sizeof(net_long) * n, 0);
if (fread(buf, sizeof(net_long), GROUP_FIELDS, f) != GROUP_FIELDS)
return 0;
net_to_host(buf, GROUP_FIELDS);
gh->first_l_article = buf[0];
gh->last_l_article = buf[1];
gh->index_write_offset = buf[2];
gh->data_write_offset = buf[3];
gh->group_name_length = buf[4];
gh->group_flag = buf[5];
#else
if (n >= 0)
fseek(f, (off_t)(sizeof(master_header) + SAVED_GROUP_HEADER_SIZE(*gh) * n), 0);
if (fread(gh, SAVED_GROUP_HEADER_SIZE(*gh), 1, f) != 1)
return 0;
#endif
return 1;
}
db_write_group(f, gh, n)
FILE *f;
register group_header *gh;
group_number n;
{
#ifdef NETWORK_DATABASE
net_long buf[GROUP_FIELDS];
if (n >= 0)
fseek(f, MASTER_FIELDS * sizeof(net_long) + GROUP_FIELDS * sizeof(net_long) * n, 0);
buf[0] = gh->first_l_article;
buf[1] = gh->last_l_article;
buf[2] = gh->index_write_offset;
buf[3] = gh->data_write_offset;
buf[4] = gh->group_name_length;
buf[5] = gh->group_flag;
host_to_net(buf, GROUP_FIELDS);
if (fwrite(buf, sizeof(net_long), GROUP_FIELDS, f) != GROUP_FIELDS)
return 0;
#else
if (n >= 0)
fseek(f, (off_t)(sizeof(master_header) + SAVED_GROUP_HEADER_SIZE(*gh) * n), 0);
if (fwrite((char *)gh, SAVED_GROUP_HEADER_SIZE(*gh), 1, f) != 1)
return 0;
#endif
return 1;
}
db_read_art(f, dh, offset)
FILE *f;
data_header *dh;
off_t *offset;
{
#ifdef NETWORK_DATABASE
net_long buf[ARTICLE_FIELDS];
if (fread(buf, sizeof(net_long), ARTICLE_FIELDS, f) != ARTICLE_FIELDS)
return 0;
net_to_host(buf, ARTICLE_FIELDS);
dh->dh_number = buf[0];
dh->dh_date = buf[1];
dh->dh_hpos = buf[2];
dh->dh_lpos = buf[3];
dh->dh_fpos = buf[4];
dh->dh_lines = buf[5];
dh->dh_replies = buf[6];
dh->dh_cross_postings = buf[7];
dh->dh_subject_length = buf[8];
dh->dh_sender_length = buf[9];
if (offset) *offset += ARTICLE_FIELDS * sizeof(net_long);
#else
if (fread((char *)dh, sizeof(data_header), 1, f) != 1) return 0;
if (offset) *offset += sizeof(data_header);
#endif
return 1;
}
db_write_art(f, dh)
FILE *f;
data_header *dh;
{
#ifdef NETWORK_DATABASE
net_long buf[ARTICLE_FIELDS];
buf[0] = dh->dh_number;
buf[1] = dh->dh_date;
buf[2] = dh->dh_hpos;
buf[3] = dh->dh_lpos;
buf[4] = dh->dh_fpos;
buf[5] = dh->dh_lines;
buf[6] = dh->dh_replies;
buf[7] = dh->dh_cross_postings;
buf[8] = dh->dh_subject_length;
buf[9] = dh->dh_sender_length;
host_to_net(buf, ARTICLE_FIELDS);
if (fwrite(buf, sizeof(net_long), ARTICLE_FIELDS, f) != ARTICLE_FIELDS)
return 0;
#else
if (fwrite((char *)dh, sizeof(data_header), 1, f) != 1) return 0;
#endif
return 1;
}
off_t get_index_offset(gh, art_num)
group_header *gh;
article_number art_num;
{
#ifdef NETWORK_DATABASE
return (off_t)((art_num - gh->first_l_article) * sizeof(net_long));
#else
return (off_t)((art_num - gh->first_l_article) * sizeof(off_t));
#endif
}
off_t get_data_offset(gh, art_num)
group_header *gh;
article_number art_num;
{
FILE *index;
off_t data_offset;
if (gh->first_l_article == art_num) return (off_t)0;
index = open_data_file(gh, 'x', OPEN_READ);
if (index == NULL) return (off_t)(-1);
fseek(index, get_index_offset(gh, art_num), 0);
if (!db_read_offset(index, &data_offset))
return (off_t)(-1);
fclose(index);
return data_offset;
}
db_read_offset(f, offset)
FILE *f;
off_t *offset;
{
#ifdef NETWORK_DATABASE
net_long temp;
if (fread(&temp, sizeof(net_long), 1, f) != 1) return 0;
#ifndef NETWORK_BYTE_ORDER
temp = ntohl(temp);
#endif
*offset = temp;
#else
if (fread((char *)offset, sizeof(off_t), 1, f) != 1) return 0;
#endif
return 1;
}
db_write_offset(f, offset)
FILE *f;
off_t *offset;
{
#ifdef NETWORK_DATABASE
net_long temp;
temp = *offset;
#ifndef NETWORK_BYTE_ORDER
temp = htonl(temp);
#endif
if (fwrite(&temp, sizeof(net_long), 1, f) != 1) return 0;
#else
if (fwrite((char *)offset, sizeof(off_t), 1, f) != 1) return 0;
#endif
return 1;
}